#include "bsp_adc.h"
#include "systick.h"
#include "gd32a508_adc.h"

#define ADC_CHL_TEMP1 ADC_CHANNEL_10 // 温度1ADC采样通道
#define ADC_CHL_TEMP2 ADC_CHANNEL_11 // 温度2ADC采样通道
#define ADC_CHL_TEMP3 ADC_CHANNEL_12 // 温度3ADC采样通道
#define ADC_CHL_TEMP4 ADC_CHANNEL_13 // 温度4ADC采样通道
#define ADC_CHL_TEMP5 ADC_CHANNEL_0  // 温度5ADC采样通道
#define ADC_CHL_TEMP6 ADC_CHANNEL_1  // 温度6ADC采样通道

#define ADC_CHL_LOADVOL ADC_CHANNEL_2 // 负载总压采样通道
#define ADC_CHL_BATVOL  ADC_CHANNEL_3  // 电池总压采样通道


dv_ADC_TypeDef dv_ADC;

static uint16_t u16ADC0_ValBuffer[ADC0_CH_NUM];

static void adc_gpio_init(void)
{
  rcu_periph_clock_enable(RCU_GPIOA);
  rcu_periph_clock_enable(RCU_GPIOC);

  gpio_init(GPIOC, GPIO_MODE_AIN, GPIO_OSPEED_MAX, GPIO_PIN_0); // temp1
  gpio_init(GPIOC, GPIO_MODE_AIN, GPIO_OSPEED_MAX, GPIO_PIN_1); // temp2
  gpio_init(GPIOC, GPIO_MODE_AIN, GPIO_OSPEED_MAX, GPIO_PIN_2); // temp3
  gpio_init(GPIOC, GPIO_MODE_AIN, GPIO_OSPEED_MAX, GPIO_PIN_3); // temp4
  gpio_init(GPIOA, GPIO_MODE_AIN, GPIO_OSPEED_MAX, GPIO_PIN_0); // temp5
  gpio_init(GPIOA, GPIO_MODE_AIN, GPIO_OSPEED_MAX, GPIO_PIN_1); // temp6

  gpio_init(GPIOA, GPIO_MODE_AIN, GPIO_OSPEED_MAX, GPIO_PIN_2); // loadvol
  gpio_init(GPIOA, GPIO_MODE_AIN, GPIO_OSPEED_MAX, GPIO_PIN_3); // batvol
}

static void adc_dma_config(void)
{
  dma_parameter_struct DMA_InitStruct;

  rcu_periph_clock_enable(RCU_DMA0);

  /* ADC_SYSAI DMA (ADC0) configuration ------------------------------------*/
  dma_deinit(DMA0, DMA_CH0);
  DMA_InitStruct.periph_addr = (uint32_t)(&ADC_RDATA(ADC0));
  DMA_InitStruct.memory_addr = (uint32_t)u16ADC0_ValBuffer;
  DMA_InitStruct.direction = DMA_PERIPHERAL_TO_MEMORY;
  DMA_InitStruct.number = ADC0_CH_NUM;
  DMA_InitStruct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
  DMA_InitStruct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
  DMA_InitStruct.periph_width = DMA_PERIPHERAL_WIDTH_16BIT;
  DMA_InitStruct.memory_width = DMA_MEMORY_WIDTH_16BIT;
  DMA_InitStruct.priority = DMA_PRIORITY_HIGH;
  dma_init(DMA0, DMA_CH0, &DMA_InitStruct);

  dma_circulation_enable(DMA0, DMA_CH0);

  dma_channel_enable(DMA0, DMA_CH0);
}
static void adc_config(void)
{
  /* enable ADC clock */
  rcu_periph_clock_enable(RCU_ADC0);
  /* config ADC clock */
  rcu_adc_clock_config(RCU_CKADC_CKAPB2_DIV6); //(12.5+55.5)*16/30 = 36us(单通道)
  /* 12BIT */
  adc_resolution_config(ADC0, ADC_RESOLUTION_12B);
  /* ADC mode config */
  adc_mode_config(ADC_MODE_FREE);
  /* ADC continuous function enable */
  adc_special_function_config(ADC0, ADC_CONTINUOUS_MODE, ENABLE);
  /* ADC scan function enable */
  adc_special_function_config(ADC0, ADC_SCAN_MODE, ENABLE);
  /* ADC data alignment config */
  adc_data_alignment_config(ADC0, ADC_DATAALIGN_RIGHT);

  adc_tempsensor_vrefint_enable();
  /* ADC channel length config */
  adc_channel_length_config(ADC0, ADC_REGULAR_CHANNEL, ADC0_CH_NUM);

  /* ADC regular channel config */
  adc_regular_channel_config(ADC0, AN_Temp1_Chl, ADC_CHL_TEMP1, ADC_SAMPLETIME_55POINT5);
  adc_regular_channel_config(ADC0, AN_Temp2_Chl, ADC_CHL_TEMP2, ADC_SAMPLETIME_55POINT5);
  adc_regular_channel_config(ADC0, AN_Temp3_Chl, ADC_CHL_TEMP3, ADC_SAMPLETIME_55POINT5);
  adc_regular_channel_config(ADC0, AN_Temp4_Chl, ADC_CHL_TEMP4, ADC_SAMPLETIME_55POINT5);
  adc_regular_channel_config(ADC0, AN_Temp5_Chl, ADC_CHL_TEMP5, ADC_SAMPLETIME_55POINT5);
  adc_regular_channel_config(ADC0, AN_Temp6_Chl, ADC_CHL_TEMP6, ADC_SAMPLETIME_55POINT5);
  adc_regular_channel_config(ADC0, AN_LoadVol_Chl, ADC_CHL_LOADVOL, ADC_SAMPLETIME_55POINT5);
  adc_regular_channel_config(ADC0, AN_BatVol_Chl, ADC_CHL_BATVOL, ADC_SAMPLETIME_55POINT5);
  adc_regular_channel_config(ADC0, AN_Chip_TMP_Chl, ADC_CHANNEL_16, ADC_SAMPLETIME_239POINT5);
  adc_regular_channel_config(ADC0, AN_Ref_Vol_Chl, ADC_CHANNEL_17, ADC_SAMPLETIME_239POINT5);

  /* ADC trigger config */
  adc_external_trigger_source_config(ADC0, ADC_REGULAR_CHANNEL, ADC0_1_EXTTRIG_REGULAR_NONE);
  adc_external_trigger_config(ADC0, ADC_REGULAR_CHANNEL, ENABLE);

  /* 16 times sample, 4 bits shift */
  adc_oversample_mode_config(ADC0, ADC_OVERSAMPLING_ALL_CONVERT, ADC_OVERSAMPLING_SHIFT_4B, ADC_OVERSAMPLING_RATIO_MUL16);
  adc_oversample_mode_enable(ADC0);

  /* ADC DMA function enable */
  adc_dma_mode_enable(ADC0);
  /* enable ADC interface */
  adc_enable(ADC0);
  delay_1ms(1);
  /* ADC calibration and reset calibration */
  adc_calibration_enable(ADC0);

  /* ADC software trigger enable */
  adc_software_trigger_enable(ADC0, ADC_REGULAR_CHANNEL);
}

static uint16_t bsp_adc_get_value(ADC_ChannelTypeDef Channel)
{
  return (float)u16ADC0_ValBuffer[Channel] * ADC_REF / 4096;  
}

static void bsp_adc_init(void)
{
  adc_gpio_init();
  adc_dma_config();
  adc_config();
}

void init_bsp_adc(void)
{
  dv_ADC.finit = bsp_adc_init;
  dv_ADC.fread = bsp_adc_get_value;
}